import { useState, type PropsWithChildren } from "react";
import {
  Form,
  Input,
  Select,
  Switch,
  Checkbox,
  Button,
  Table,
  InputNumber,
  Spin,
} from "antd";
import { useAtomValue } from "jotai";
import Upload from "./Upload";
import SaveIcon from "@/assets/images/diskette.png?jsx";
import type { IDevice, IMaker, IRegion } from "@/lib/types";
import useFetch from "@/lib/hooks/useFetch";
import { tokenAtom } from "@/store/user";
import { createDevice, getDeviceDetail, updateDevice } from "@/lib/api/device";
import { useMessage } from "@/providers/AntdMessageProvider";
import useOnUpdated from "@/lib/hooks/useOnUpdated";
import { randomStr } from "@/lib/utils/random";
import FullSizeModal from "@/components/FullSizeModal";
import Monitors, { type Monitor } from "./Monitors";
import getRequestErrorMessage from "@/lib/utils/getRequestErrorMessage";
import clsm from "@/lib/utils/clsm";

type IFormData = Omit<
  IDevice,
  "monitors" | "alarms" | "isTemperature" | "isHumidity" | "isPressure"
> & {
  /** 1-T 2-H 3-P */
  deviceType: number[];
  alarms: (IDevice["alarms"][number] & { _id: string })[];
  monitors: (Monitor & { _id: string })[];
};
type EditDialogProps = {
  type?: "create" | "edit" | "copy";
  record?: IDevice;
  visible: boolean;
  onVisibleChange: (v: boolean) => void;
  reloadList: () => void;
  makerList: IMaker[];
  regionList: IRegion[];
};

export default function EditDialog(props: EditDialogProps) {
  const {
    type,
    record,
    visible,
    onVisibleChange,
    reloadList,
    makerList,
    regionList,
  } = props;
  const message = useMessage();
  const [protocol, setProtocol] = useState<string>();
  const [form] = Form.useForm();

  const token = useAtomValue(tokenAtom);

  const { isLoading, refetch: getDetail } = useFetch({
    fetchFn: (id: number) =>
      getDeviceDetail(id, token).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
        return res.data;
      }),
    onSuccess(data) {
      const {
        isHumidity,
        isPressure,
        isTemperature,
        monitors,
        alarms,
        protocol,
        ...rest
      } = data;
      setProtocol(protocol);
      const fields = {
        protocol,
        ...rest,
        deviceType: [
          isTemperature && 1,
          isHumidity && 2,
          isPressure && 3,
        ].filter(Boolean),
        monitors: monitors.map((el) => ({
          _id: randomStr(),
          ...el,
        })),
        alarms: alarms.map((el) => ({
          _id: randomStr(),
          id: el.id,
          name: el.name,
          sign: el.sign,
        })),
      } as IFormData;
      console.log(fields);
      form.setFieldsValue(fields);
    },
  });

  function handleSave(data: IFormData) {
    __DEV__ && console.log("save device", data);
    const { deviceType = [], monitors = [], alarms = [], ...rest } = data;
    const payload: Partial<IDevice> = {
      ...rest,
      isTemperature: deviceType.includes(1) ? 1 : 0,
      isHumidity: deviceType.includes(2) ? 1 : 0,
      isPressure: deviceType.includes(3) ? 1 : 0,
      monitors: monitors.map(({ _id, ...rest }) => rest),
      alarms: alarms.map(({ _id, ...rest }) => rest),
    };
    __DEV__ && console.log("create device", payload);
    let handler: Promise<any>;
    if (type === "create" || type === "copy") {
      handler = createDevice(payload, token).then((res) => {
        console.log(res);
        if (res.code !== 200) {
          throw res;
        }
        return res;
      });
    } else {
      payload.deviceId = record!.deviceId;
      handler = updateDevice(payload, token).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
        return res;
      });
    }
    handler
      .then((res) => {
        message.success(res.msg);
        reloadList();
        onVisibleChange(false);
      })
      .catch((error) => {
        const _message = getRequestErrorMessage(
          error,
          `${type === "create" ? "添加" : type === "edit" ? "更新" : "复制"}失败，请稍后再试！`,
        );
        message.error(_message);
      });
  }

  useOnUpdated(() => {
    if (visible) {
      if ((type === "edit" || type === "copy") && record) {
        getDetail(record.deviceId);
      } else if (type === "create") {
        form.resetFields();
      }
    }
  }, [visible, record, type]);

  return (
    <FullSizeModal
      visible={visible}
      onClose={() => onVisibleChange(false)}
      title={`${type === "create" ? "添加" : type === "edit" ? "编辑" : "复制"}设备`}
      fullscreen
    >
      <div className="h-full overflow-auto p-8">
        <Spin spinning={isLoading}>
          <Form layout="vertical" onFinish={handleSave} form={form}>
            <div className="grid grid-cols-2 gap-x-8">
              <div>
                <Form.Item label="设备名称" name="deviceName">
                  <Input />
                </Form.Item>
                <Form.Item label="设备类型" name="deviceType">
                  <Checkbox.Group
                    options={[
                      { label: "温度", value: 1 },
                      { label: "湿度", value: 2 },
                      { label: "真空", value: 3 },
                    ]}
                  />
                </Form.Item>
              </div>
              <div className="flex justify-end">
                <Form.Item name="imagePath">
                  <Upload />
                </Form.Item>
              </div>
              <Form.Item label="厂家" name="makerId">
                <Select
                  options={makerList.map((el) => ({
                    label: el.makerName,
                    value: el.makerId,
                  }))}
                />
              </Form.Item>
              <Form.Item label="编号" name="number">
                <Input />
              </Form.Item>
              <Form.Item label="型号" name="type">
                <Select
                  options={[
                    { label: "CB284", value: "CB284" },
                    { label: "YYK", value: "YYK" },
                    { label: "FRD", value: "FRD" },
                    { label: "YXB25", value: "YXB25" },
                    { label: "YXB27", value: "YXB27" },
                  ]}
                />
              </Form.Item>
              <Form.Item label="区域" name="regionId">
                <Select
                  options={regionList.map((el) => ({
                    label: el.regionName,
                    value: el.regionId,
                  }))}
                />
              </Form.Item>
              <div className="flex justify-between *:flex-none *:basis-[48%]">
                <Form.Item label="协议" name="protocol">
                  <Select
                    onChange={setProtocol}
                    options={[
                      { label: "ModbusTcp", value: "ModbusTcp" },
                      { label: "ModbusRtu", value: "ModbusRtu" },
                    ]}
                  />
                </Form.Item>
                <Button className="mt-[30px]">测试连接</Button>
              </div>
              {protocol === "ModbusTcp" && (
                <div className="flex gap-x-5">
                  <div className="flex flex-auto gap-x-4">
                    <Form.Item className="flex-auto" label="IP" name="ip">
                      <Input className="basis-2/3" />
                    </Form.Item>
                    <Form.Item className="basis-40" label="端口" name="port">
                      <Input />
                    </Form.Item>
                  </div>
                </div>
              )}
              {protocol === "ModbusRtu" && (
                <>
                  <Wrapper>
                    <Form.Item label="串口号" name="serialPort">
                      <Input />
                    </Form.Item>
                    <Form.Item label="波特率" name="baudRate">
                      <InputNumber className="w-full" min="0" max="65535" />
                    </Form.Item>
                  </Wrapper>
                  <Wrapper>
                    <Form.Item label="DataBits" name="dataBits">
                      <Select
                        options={[
                          { label: "7", value: "7" },
                          { label: "8", value: "8" },
                        ]}
                      />
                    </Form.Item>
                    <Form.Item label="Parity" name="parity">
                      <Select
                        options={[
                          { label: "0", value: "0" },
                          { label: "1", value: "1" },
                          { label: "2", value: "2" },
                          { label: "3", value: "3" },
                          { label: "4", value: "4" },
                        ]}
                      />
                    </Form.Item>
                  </Wrapper>
                  <Wrapper>
                    <Form.Item label="StopBits" name="stopBits">
                      <Select
                        options={[
                          { label: "1", value: "1" },
                          { label: "2", value: "2" },
                          { label: "3", value: "3" },
                        ]}
                      />
                    </Form.Item>
                    <Form.Item label="串口类型" name="rsMode">
                      <Select
                        options={[
                          { label: "rs232", value: "rs232" },
                          { label: "rs485", value: "rs485" },
                        ]}
                      />
                    </Form.Item>
                  </Wrapper>
                </>
              )}
              <Wrapper>
                <Form.Item label="高温" name="temperatureHigh">
                  <InputNumber className="w-full" />
                </Form.Item>
                <Form.Item label="低温" name="temperatureLow">
                  <InputNumber className="w-full" />
                </Form.Item>
              </Wrapper>
              <Wrapper>
                <Form.Item label="高湿" name="humidityHigh">
                  <InputNumber className="w-full" />
                </Form.Item>
                <Form.Item label="低湿" name="humidityLow">
                  <InputNumber className="w-full" />
                </Form.Item>
              </Wrapper>
              <Wrapper>
                <Form.Item label="高压" name="pressureHigh">
                  <InputNumber className="w-full" />
                </Form.Item>
                <Form.Item label="低压" name="pressureLow">
                  <InputNumber className="w-full" />
                </Form.Item>
              </Wrapper>
              <Wrapper>
                <Form.Item label="存储" name="store">
                  <Select
                    options={[
                      { label: "运行时", value: 0 },
                      { label: "全部", value: 1 },
                    ]}
                  />
                </Form.Item>
                <Form.Item label="间隔" name="storeIntervalTime">
                  <InputNumber className="w-full" />
                </Form.Item>
              </Wrapper>
              {/* <Form.Item label="报警" name="alarms">
                <Alarms />
              </Form.Item> */}
              <Form.Item label="指令">
                <Select />
              </Form.Item>
              <Wrapper className="col-span-2">
                <Form.Item
                  label="测量点"
                  className="w-full !flex-auto"
                  name="monitors"
                >
                  <Monitors />
                </Form.Item>
              </Wrapper>
              <div className="flex items-end justify-center">
                <Button className="relative basis-3/5" htmlType="submit">
                  <SaveIcon className="absolute left-2 w-5" />
                  保存
                </Button>
              </div>
            </div>
          </Form>
        </Spin>
      </div>
    </FullSizeModal>
  );
}

function Wrapper({
  children,
  className,
}: PropsWithChildren<{ className?: string }>) {
  return (
    <div
      className={clsm(
        "flex justify-between *:flex-none *:basis-[48%]",
        className,
      )}
    >
      {children}
    </div>
  );
}

type AlarmItem = { _id: string; id: string; name: string; sign: string };
type AlarmsProps<T = AlarmItem> = {
  value?: T[];
  onChange?: (data: T[]) => void;
};

function Alarms(props: AlarmsProps) {
  const { value = [], onChange } = props;

  function handleNewRecord() {
    onChange?.([...value, { _id: randomStr(), id: "", sign: "", name: "" }]);
  }

  function handleDeleteRecord<T extends { _id: string }>(record: T) {
    onChange?.(value.filter((el) => el._id !== record._id));
  }

  const dataSource = value.concat({
    _id: "new_item_button",
    id: "",
    name: "",
    sign: "",
  });

  return (
    <Table dataSource={dataSource} rowKey={(row) => row._id} pagination={false}>
      <Table.Column
        title="编号"
        render={(row) =>
          row._id === "new_item_button" ? (
            <div className="flex justify-center">
              <Button type="primary" onClick={handleNewRecord}>
                添加
              </Button>
            </div>
          ) : (
            <Input
              value={row.id}
              onInput={(e) =>
                onChange?.(
                  value.map((el) =>
                    el._id === row._id
                      ? { ...el, id: (e.target as HTMLInputElement).value }
                      : el,
                  ),
                )
              }
            />
          )
        }
        onCell={(row) => (row._id === "new_item_button" ? { colSpan: 4 } : {})}
      />
      <Table.Column
        title="报警号"
        render={(row) => (
          <Input
            value={row.sign}
            onInput={(e) =>
              onChange?.(
                value.map((el) =>
                  el._id === row._id
                    ? { ...el, sign: (e.target as HTMLInputElement).value }
                    : el,
                ),
              )
            }
          />
        )}
        onCell={(row) => (row._id === "new_item_button" ? { colSpan: 0 } : {})}
      />
      <Table.Column
        title="报警名"
        render={(row) => (
          <Input
            value={row.name}
            onInput={(e) =>
              onChange?.(
                value.map((el) =>
                  el._id === row._id
                    ? { ...el, name: (e.target as HTMLInputElement).value }
                    : el,
                ),
              )
            }
          />
        )}
        onCell={(row) => (row._id === "new_item_button" ? { colSpan: 0 } : {})}
      />
      <Table.Column
        render={(row) => (
          <Button size="small" onClick={() => handleDeleteRecord(row)}>
            删除
          </Button>
        )}
        onCell={(row) => (row._id === "new_item_button" ? { colSpan: 0 } : {})}
      />
    </Table>
  );
}
